\section{extern “C”与C/C++混合编程}

标准头文件都有类似以下的结构:
\begin{lstlisting}[language=C]
#ifndef __INCvxWorksh
#define __INCvxWorksh 
#ifdef __cplusplus
extern "C" {
#endif 
/*...*/ 
#ifdef __cplusplus
}
#endif 
#endif /* __INCvxWorksh */
\end{lstlisting} 

extern "C" 包含双重含义，从字面上即可得到：首先，被它修饰的目标是“extern”的；其次，被它修饰的目标是“C”的。extern是C/C++语言中表明函数和全局变量作用范围（可见性）的关键字，该关键字告诉编译器，其声明的函数和变量可以在本模块或其它模块中使用。

C++支持函数重载，函数被C++编译后在符号库中的名字与C语言的不同。例如，假设某个函数的原型为\verb|void foo(int x, int y);|。该函数被C编译器编译后在符号库中的名字为\_foo，而C++编译器则会产生像\verb|_foo_int_int|之类的名字（不同的编译器可能生成的名字不同，但是都采用了相同的机制，生成的新名字称为“mangled name”）。

同样地，C++中的变量除支持局部变量和全局变量外，还支持类成员变量。用户所编写程序的类成员变量可能与全局变量同名，我们以"."来区分。而本质上，编译器在进行编译时，与函数的处理相似，也为类中的变量取了一个独一无二的名字，这个名字与用户程序中同名的全局变量名字不同。

C++提供了C连接交换指定符号extern “C”解决名字匹配问题。 

\subsection{在C++中引用C语言中的函数和变量}

如果C++调用一个C语言编写的.DLL时，当包括.DLL的头文件或声明接口函数时，应加extern "C" {　}。
在C++中引用C语言中的函数和变量，在包含C语言头文件（假设为cExample.h）时，需进行下列处理：
\begin{lstlisting}[language=C]
 extern "C"
{
#include "cExample.h"
}

\end{lstlisting} 
　　而在C语言的头文件中，对其外部函数只能指定为extern类型，C语言中不支持extern "C"声明，在.c文件中包含了extern "C"时会出现编译语法错误。
　　例如，工程中包含的三个文件的源代码如下：
\begin{lstlisting}[language=C]
 /* c语言头文件：cExample.h */
#ifndef C_EXAMPLE_H
#define C_EXAMPLE_H
extern int add(int x,int y);
#endif

/* c语言实现文件：cExample.c */
#include "cExample.h"
int add( int x, int y )
{
return x + y;
}

// c++实现文件，调用add：cppFile.cpp
extern "C" 
{
#include "cExample.h"
}

int main(int argc, char* argv[])
{
add(2,3); 
return 0;
}

\end{lstlisting} 


\subsection{在C中引用C++语言中的函数和变量}
在C中引用C++语言中的函数和变量时，C++的头文件需添加extern "C"，但是在C语言中不能直接引用声明了extern "C"的该头文件，应该仅将C文件中将C++中定义的extern "C"函数声明为extern类型。

例如三个文件的源代码如下：
\begin{lstlisting}[language=C++]
 //C++头文件 cppExample.h
#ifndef CPP_EXAMPLE_H
#define CPP_EXAMPLE_H
extern "C" int add( int x, int y );
#endif
//C++实现文件 cppExample.cpp
#include "cppExample.h"
int add( int x, int y )
{
return x + y;
}
/* C实现文件 cFile.c
/* 这样会编译出错：#include "cExample.h" */
extern int add( int x, int y );
int main( int argc, char* argv[] )
{
add( 2, 3 ); 
return 0;
}
\end{lstlisting} 

